package com.apes.scm.advanceOrder.service;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.apes.framework.api.DomainService;
import com.apes.framework.jpa.spec.JpaDsl;
import com.apes.framework.plugin.esb.api.SimpleRequest;
import com.apes.framework.plugin.event.Listener;
import com.apes.framework.util.MapUtil;
import com.apes.scm.account.ledger.service.LedgerService;
import com.apes.scm.advanceOrder.model.AdvanceOrder;
import com.apes.scm.advanceOrder.repository.AdvanceOrderRepository;
import com.apes.scm.settle.payment.model.Payment;
import com.apestech.framework.json.JSON;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * 功能：预付款/预收款
 *
 * @author pengyb
 * @create 2018 -12-03
 */

@Service("advanceOrderService")
public class AdvanceOrderService extends DomainService {

    @Autowired
    AdvanceOrderRepository advanceOrderRepository;

    @Autowired
    LedgerService ledgerService;

    /**
     * 创建预付(收)款单
     *
     * @param request
     * @return
     * @throws RuntimeException
     */
    public AdvanceOrder create(SimpleRequest request) throws RuntimeException {
        AdvanceOrder advanceOrder = request.getO(AdvanceOrder.class);

        checkContract(advanceOrder);    // 检查合同
        advanceOrder.setAccount(advanceOrder.getBankAccountId().getAccountName());
        advanceOrder.setState("sent");
        return advanceOrderRepository.saveAndFlush(advanceOrder);
    }

    /**
     * 检查合同
     * @param advanceOrder
     *
     */
    private void checkContract(AdvanceOrder advanceOrder) {
        String contractCode = advanceOrder.getContract().getContractType().getCode().toUpperCase();
        String advanceTypeCode = advanceOrder.getAdvanceType().getCode();

        // （advReceipt：预收款；advPayment：预付款）
        if ("advPayment".equals(advanceTypeCode) && (!"SUPPLIER".equals(contractCode) && !"PLATFORM".equals(contractCode))){
            throw new RuntimeException("单据类型为预付款时，只能选择采购合同！");

        } else if ("advReceipt" .equals(advanceTypeCode) && !"CUSTOMER".equals(contractCode) ) {
            throw new RuntimeException("单据类型为预收款时，只能选择销售合同！");
        }
    }

    /**
     * 检查数据
     *
     * @param request
     */
    public void checkData(SimpleRequest request) {
        AdvanceOrder advanceOrder = advanceOrderRepository.findOne((String) request.get("id"));
        if (advanceOrder == null) throw new RuntimeException("款单：" + request.get("id") + "在系统中不存在");
        if (advanceOrder.getVersion() != (int) request.get("version")) throw new RuntimeException("记录已更新或已删除，请重新提交!");
//        if (advanceOrder.getDateApprove() != null) throw new RuntimeException("已审核");
    }

    /**
     * 修改款单
     *
     * @param request
     * @return
     * @throws RuntimeException
     */
    public AdvanceOrder update(SimpleRequest request) throws RuntimeException {
        checkData(request);
        AdvanceOrder advanceOrder = request.getO(AdvanceOrder.class);

        checkContract(advanceOrder);        // 检查合同
        advanceOrder.setAccount(advanceOrder.getBankAccountId().getAccountName());
        advanceOrder.setState("sent");
        return advanceOrderRepository.saveAndFlush(advanceOrder);
    }

    /**
     * 删除
     *
     * @param request
     * @return
     */
    public String delete(SimpleRequest request) {
        checkData(request);
        AdvanceOrder advanceOrder = request.getO(AdvanceOrder.class);

        advanceOrder.setState("delete");
        advanceOrder.setDeleteDate(new Date());
        advanceOrder.setDeleteUID(getPerson(request));

        advanceOrderRepository.delete(advanceOrder);
        return "删除成功！";
    }

    /**
     * 审批拒绝
     *
     * @param request
     * @return
     */
    public AdvanceOrder refuse(SimpleRequest request) {
        checkData(request);
        AdvanceOrder advanceOrder = request.getO(AdvanceOrder.class);

        advanceOrder.setState("sent");
        advanceOrder.setDateApprove(new Date());
        advanceOrder.setApproveUID(getPerson(request));
        return  advanceOrderRepository.saveAndFlush(advanceOrder);
    }
    /**
     * 发起oa
     *
     * @param request
     * @return
     */
    public AdvanceOrder oa(SimpleRequest request) {
        checkData(request);
        AdvanceOrder advanceOrder = request.getO(AdvanceOrder.class);
        advanceOrder.setState("oa");
        return  advanceOrderRepository.saveAndFlush(advanceOrder);
    }

    /**
     * 审核款单
     *
     * @param request
     * @return
     */
    public AdvanceOrder approve(SimpleRequest request) {
        checkData(request);
        AdvanceOrder advanceOrder = request.getO(AdvanceOrder.class);

        advanceOrder.setState("approve");
        advanceOrder.setDateApprove(new Date());
        advanceOrder.setApproveUID(getPerson(request));

        advanceOrder = advanceOrderRepository.saveAndFlush(advanceOrder);

        // 创建收付款登记
        createPaymentExecuteRecord(advanceOrder);

        return advanceOrder;
    }

    /**
     * 审核时写入收付款记录
     * @param advanceOrder 收付款登记
     */
    private void createPaymentExecuteRecord(AdvanceOrder advanceOrder){
        Map<String, Object> companyMap = new HashMap<>();
        companyMap.put("id", advanceOrder.getCompany().getId() );

        Map<String, Object> partnerMap = new HashMap<>();
        partnerMap.put("id", advanceOrder.getPartner().getId() );

        Map<String, Object> deptMap = new HashMap<>();
        deptMap.put("id", advanceOrder.getDept().getId() );

        Map map = MapUtil.mapper(
                "company", companyMap, "dept", deptMap, "partner", partnerMap,
                "originBusinessType", advanceOrder.getInnerBusinessType(),
                "origin", advanceOrder.getId(),
                "accountBank", advanceOrder.getAccount(),
                "bank", advanceOrder.getBank(),
                "bankAccount", advanceOrder.getBankAccount(),
                "subbranch", advanceOrder.getSubbranch(),
                "amount", advanceOrder.getAmount()
        );
        this.invoke("paymentExecuteRecord.create", map);
    }


    /**
     * 收款的时候回调
     * @param request
     * @return
     */
    @Listener(topic = "event:payment.pay")
    public boolean pay (SimpleRequest request) {
        JSONObject json = request.getJO();
        if (!json.getString("originBusinessType").equals(AdvanceOrder.class.getSimpleName())) return false;

        AdvanceOrder advanceOrder = advanceOrderRepository.findOne(json.getString("origin"));

        // 账目：增加预收预付款
        ledgerService.charge(advanceOrder.getCompany(),
                advanceOrder.getDept(),
                advanceOrder.getPartner(), advanceOrder.getCooperation().getInventoryMode(),
                advanceOrder.getCooperation().getAccountingMethod(),
                advanceOrder.getInnerBusinessKey(), advanceOrder.getInnerBusinessType(),
                new Date(), "prepayment_unsettled", advanceOrder.getAmount());
        advanceOrder.setState("done");
        advanceOrderRepository.save(advanceOrder);
        return true;
    }

    public com.apestech.framework.json.JSONObject query(SimpleRequest request) throws Exception {
        JSONObject jo = request.getJO();
        JSONArray condition = jo.getJSONArray("condition");
        if (condition != null) {
            for (int i = 0; i < condition.size(); i++) {
                JSONObject newJsonObject = (JSONObject)condition.getJSONObject(i).clone();
                if ("ENTRY_DATE".equals(condition.getJSONObject(i).getString("field")) &&
                    "GTE".equals(condition.getJSONObject(i).getString("operator"))
                ) {
                    newJsonObject.put("field", "ENTRY_DATE_BEGIN");
                    newJsonObject.put("operator", "EQ");
                    newJsonObject.remove("type");
                    condition.add(newJsonObject);
                } else if ("ENTRY_DATE".equals(condition.getJSONObject(i).getString("field")) &&
                        "LTE".equals(condition.getJSONObject(i).getString("operator"))
                ) {
                    newJsonObject.put("operator", "EQ");
                    newJsonObject.remove("type");
                    newJsonObject.put("field", "ENTRY_DATE_END");
                    condition.add(newJsonObject);
                }

            }
            jo.put("condition", condition);
        }
        return JSON.toJSON(jo.toJSONString());
    }
    /**
     * 付款单回写预付款申请单
     *
     * @param request
     * @return
     * @throws RuntimeException
     */
    public void payment(SimpleRequest request) throws RuntimeException {
        Map<String, Object> map = new HashMap<>(request.get("data"));
        List<AdvanceOrder> advanceOrderList =new ArrayList<>();
        Payment payment = (Payment) map.get("payment");
        payment.getPaymentItemSet().stream().forEach(v -> {
            if (Objects.isNull(v.getOrigin())) return;
            AdvanceOrder paymentAdvanceOrder = advanceOrderRepository.findOne(v.getOrigin());
            if(Objects.isNull(paymentAdvanceOrder)) return;
            paymentAdvanceOrder.setPaymentDate(payment.getApproveDate());

            JSONArray fileAddress = JSONArray.parseArray(payment.getFileAddres());
            JSONArray settlementPNG = new JSONArray();
            if (Objects.nonNull(v.getPayment().getFileAddres())) {
                settlementPNG = JSONArray.parseArray(v.getPayment().getFileAddres());
                fileAddress.addAll(settlementPNG);
            }
            paymentAdvanceOrder.setFileAddres(v.getPayment().getFileAddres());
            advanceOrderList.add(paymentAdvanceOrder);
        });
        advanceOrderRepository.saveAll(advanceOrderList);
    }
}
